﻿ 
#include "stdafx.h"
#include "core.h"
#include "functions.h"
#include "export_functions.h"

	  

//===========================================================

Core*  g_core = NULL;

 CORE_API void DoCreateCore()  throw (Error)
{
	if(g_core)
	{
		throw Error("Core object is already created");
	}

	g_core = new Core;
}

 CORE_API Core* GetGore()
{
	assert(g_core);

	return g_core;
}

//=============================================================
Core::Core() throw (Error)
{
	m_isrun = true;

	//m_userInfoList = NULL;
	m_currentUserIndex = -1;

	// create dictionary
	{
		std::wstring fpath;
		fpath += GetDictDirectory();
		fpath += L"Dict.txt";
		m_Dictionary.reset( new Dictionary( fpath ) );
	}
	// new (create dictionary)
	

	try
	{
		m_dlguifLoader.reset( new dlguif::Loader(NULL) );
	}
	catch(...)
	{
		MessageError("Error load dlguif.dll");
		throw Error("Error load dlguif.dll");
	}
	


	// test WOrdsWeight
	//WordsWeight* ww = GetWordsWeight();		
	//UINT wwuint = ww->GetWordWeightUint("may");



	// test category
	CategoryList* cl = GetCategoryList();



	int _end =0;
}

Core::~Core()
{
	
	//if(m_dlguifLoader)
	//{
	//	delete m_dlguifLoader;
	//	m_dlguifLoader = NULL;
	//}


	m_isrun = false;

	//if(m_userInfoList)
	//{
	//	delete m_userInfoList;
	//	m_userInfoList = NULL;
	//}


}

std::wstring Core::GetExeDirectory()
{
	 WCHAR temp[512];
	 memset(temp, 0, sizeof(WCHAR)*512 );
	 ::GetModuleFileNameW(NULL, temp, 512);
	 const size_t LEN = wcslen(temp);
	 for (size_t i = LEN; i >= 0; i--)
	 {
			if ( temp[i] == L'\\')
			{
				//memcpy (lpBuffer, lpFilePath, (i+1) * sizeof(WCHAR)   );
				//lpBuffer [i+1] = '\0';
				//return true;
				break;
			}

			temp[i] = L'\0';
	 }

	 std::wstring res (temp);
	 return res;
}


int Core::Initialize(PCoreInitData pcid, PGuiCallbackData pccd )
{
	

	// check dirs
	if(!ksfilefunc::directoryExistW((LPWSTR)GetUsersDirectory().c_str()))
	{
		MessageError("Директория \"users\" не найдена. Пожалуйста переустановите приложение.");
		//return -1;
		exit(-1);
	}
 
	if(!ksfilefunc::directoryExistW((LPWSTR)GetDictDirectory().c_str()))
	{
		MessageError("Директория \"dict\" не найдена. Пожалуйста переустановите приложение.");
		//return -1;
		exit(-1);
	}

	if(!ksfilefunc::directoryExistW((LPWSTR)GetSoundDirectory().c_str()))
	{
		MessageError("Директория \"sound\" не найдена. Пожалуйста переустановите приложение.");
		//return -1;
		exit(-1);
	}

 

	// create users
	m_userInfoList.reset( new UserInfoList( GetUsersDirectory() ) );
	
	{
		if(m_userInfoList->GetNumUsers() == 0)
		{
			// users not found !
			MessageInfo("Ни одного созданного пользователя не найдено! \nСейчас вы создадите пользователя.");
			// const char* startUserName,  char* dest, PNewUserTypeEnum nute
			TNewUserTypeEnum usertype = UNDEFINED;
			char dest_new_username [32];

			while(true)
			{

				if(pccd->func_CallFromDll_DialogNewUserExecute("NewUser0", dest_new_username, &usertype) )
				{
					if(m_userInfoList->IsUserExists( std::string(dest_new_username) ))
					{
						std::string temp ;
						temp += "Пользователь ";
						temp +=  dest_new_username;
						temp += " уже существует. \nЗадайте другое имя пользователя";
						MessageError(temp);
						continue;;
					}

					// тут код создания нового пользователя и его сохранение
					UserInfo* pUser = m_userInfoList->AddUser( std::string(dest_new_username) );
					{
						std::string temp;
						std::string struser = dest_new_username;
						temp += "Пользователь ";
						temp += "\"";
						temp += struser;
						temp += "\""; 
						temp += " успешно создан !";
						MessageInfo( temp );
					}
					
					break; 

				}
				else
				{
					// отменено создание пользователя
					MessageInfo("Создание пользователя отменено. Программа закрывается.");
					exit(0);
				}

			}

		}
		else
		{
			// Пользователи найдены и загружены

			while(true)
			{
				std::string userline =  m_userInfoList->MakeUsersLine();
				int res_select_user = pccd->func_CallFromDll_DialogSelectUser(userline.c_str());
				if(res_select_user == -1)
				{
					MessageInfo("Пользователь не выбран. Программа будет закрыта");
					exit(0);
				}

				// проверка на удаление
				{
					int leftBites = res_select_user;
					leftBites = leftBites | 0x0000ffff;
					leftBites = leftBites ^ 0x0000ffff;
					leftBites = leftBites >> 16;

					int rightBites = res_select_user;
					rightBites = rightBites | 0xffff0000;
					rightBites = rightBites ^ 0xffff0000;



					if(leftBites == 1)
					{		
						// удаление пользоватеня
						std::string tempstr;
						tempstr += "Удалить пользователя \"";
						tempstr +=m_userInfoList->GetUser(rightBites)->GetUserName();
						tempstr += "\" ?";
						if( MessageAsk( tempstr.c_str() ) )
						{
							assert( rightBites != -1 && " ИНДЕКС ДОЛЖЕН БЫТЬ ВАЛИДЕН " );
							GetUserInfoList()->DeleteUser( m_userInfoList->GetUserNameIndex(rightBites) );
							continue;
						}
						else
						{
							continue;
						}
					} // if(leftBites == 1)

					if(leftBites == 2)
					{
						// команда создания пользователя

						// const char* startUserName,  char* dest, PNewUserTypeEnum nute 
						char dest[32];
						memset(dest, 32, 0);
						TNewUserTypeEnum nute;
						if(pccd->func_CallFromDll_DialogNewUserExecute("newUser", dest, &nute) )
						{
							// создание нового пользвателя
							try
							{
								m_userInfoList->AddUser(std::string(dest) );
							}
							catch(Error e)
							{
								MessageError("Ошибка создания пользователя");
								throw e;
							}


							continue;
						}
						else
						{
							// отмена создания
							continue;
						}



					}
				}

				this->SelectUser( m_userInfoList->GetUser(res_select_user)->GetUserName() );


				break;
			}


			
			 

			//assert( false && "  Показать диалог выбора пользователя  ");
			 
			// int (__stdcall *TFunc_CallFromDll_DialogSelectUser)(const char* users);
			/*
			std::string users_items;
			for(size_t c=0; c<foundFiles.size()-1; c++)
			{
				users_items += ksstr::convertWstringToAstringWinapi(foundFiles[c]);
				if(c != foundFiles.size()-1)
				{
					// not last
					users_items += "\n";
				}
			}
			*/


			



			



		}
	}




	return 0;
}

UserInfo* Core::GetCurrentUser() throw(Error)
{
	if(m_currentUserIndex == -1)
	{
		//throw Error("No select user");
		return NULL;
	}

	UserInfo* res = m_userInfoList->GetUser( (size_t)m_currentUserIndex );
	return res;
}

void Core::SelectUser(const std::string& user_name) throw(Error)
{
	if(!m_userInfoList->IsUserExists(user_name))
	{
		std::string temp = "User ";
		temp += user_name;
		temp += " not found!";
		throw Error(temp);
	}

	int index = m_userInfoList->GetUserIndex(user_name);
	if(index == -1)
	{
		std::string temp = "User ";
		temp += user_name;
		temp += " not found!";
		throw Error(temp);
	}

	if(this->GetCurrentUser())
	{
		this->GetCurrentUser()->Save();
	}
	

	m_currentUserIndex = this->m_userInfoList->GetUserIndex(user_name);

	CoreLogMessage("  NEED CODE  Core::SelectUser  ");
	

}
 
 /*
int Core::Run( PCoreRunParams rp )
{

   HRESULT hr = 0;

	while(true)
	{
 
		try
		{
			hr = rp->funcProcessMessages(rp->user_ptr);
		}
		catch (...)
		{
			Messg("Exception");
			break;
		}

		if(!m_isrun) 
		{
			break;
		}
		else
		{
			int vvv = 0;
		}

		if(hr == S_FALSE)
		{
			break;
		}

		if FAILED(hr)
		{
			HandleError(__FILE__, __LINE__, "Error call: rp->funcProcessMessages(rp->user_ptr);");
		}


		Sleep(1);
	}




	return 0;
}
*/

void Core::Finalize()
{
	m_isrun = false;
}


std::wstring Core::GetUsersDirectory() const
{
	std::wstring users_path = ksfilefunc::getExeFullPaths_W() + L"users\\";
	return users_path;
}
 
std::wstring Core::GetDictDirectory() const
{
	std::wstring dict_Path = ksfilefunc::getExeFullPaths_W() + L"dict\\";
	return dict_Path;
}

std::wstring Core::GetSoundDirectory() const
{
	std::wstring dict_Path = ksfilefunc::getExeFullPaths_W() + L"sound\\";
	return dict_Path;
}

std::wstring Core::GetWordWeightPath() const
{
	std::wstring res = ksfilefunc::getExeFullPaths_W();
	res += L"WordWeight\\WordWeight.txt";

	if(!ksfilefunc::fileExistsW(res.c_str()))
	{
		throw Error("Путь к файлу веса слов не найден");
	}

	return res;
}

std::wstring Core::GetCategoryDirectory() const
{
	std::wstring res = ksfilefunc::getExeFullPaths_W();
	res += L"category\\";
	return res;
}

Dictionary* Core::GetDictionary()
{
	assert( m_Dictionary.get() && " m_Dictionary is null " );
	return m_Dictionary.get();
}

Config* Core::GetGonfig()
{
	if( !m_config.get() )
	{
		std::wstring fulllpath = GetExeDirectory();
		fulllpath += L"config.ini";
		m_config.reset( new Config(fulllpath) );
	}

	return m_config.get();
}

WordsWeight* Core::GetWordsWeight()
{
	if(m_WordsWeight.get() == NULL)
	{
		m_WordsWeight.reset( new WordsWeight( GetWordWeightPath().c_str() ) );
	}
 
	return m_WordsWeight.get();
}

CategoryList* Core::GetCategoryList()
{
	if(m_CategoryList.get() == NULL)
	{
		m_CategoryList.reset( new CategoryList( GetCategoryDirectory().c_str() ) );
	}

	 return m_CategoryList.get();
}
 

//=========================================================================


class ___initialize_core_cpp
{
public:

	___initialize_core_cpp()
	{
		 int temp =0;
	}

	~___initialize_core_cpp()
	{
		 if(g_core)
		 {
			 delete g_core;
			 g_core = NULL;
		 }
	}
};	static ___initialize_core_cpp  _____initialize_core_cpp;
	   